﻿using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Infrastructure.Job
{
    public static class JobExtensions
    {
        public static IApplicationBuilder UseJob(this IApplicationBuilder app,string PrifxNamespace= "Application.Job")
        {
            var env = app.ApplicationServices.GetService<IHostEnvironment>();
            var lifetime = app.ApplicationServices.GetService<IHostApplicationLifetime>();
            JobManager jobManager = JobManager.GetInstance();

            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

            var type = typeof(AbstractJob);
            var attributeType = typeof(JobAttribute);

            try
            {
                lifetime.ApplicationStarted.Register(() =>
                {
                    foreach (var assembly in assemblies)
                    {
                        foreach (var item in assembly.GetTypes().Where(i => i.IsSubclassOf(type) && i.FullName.StartsWith(PrifxNamespace)))
                        {
                            var attr = (JobAttribute)item.GetCustomAttributes(attributeType, true).FirstOrDefault();

                            if (attr == null) throw new JobException("未找到任务运行设置 JobAttribute  Class:" + item.FullName);

                            ScheduleInfo scheduleInfo = new ScheduleInfo();

                            scheduleInfo.JobGroup = string.IsNullOrWhiteSpace(attr.JobGroup) ? env.ApplicationName : attr.JobGroup;

                            if (string.IsNullOrWhiteSpace(attr.StarRunTime))
                            {
                                scheduleInfo.StarRunTime = DateTime.Now;
                            }
                            else
                            {
                                var startTime = DateTimeOffset.Parse(attr.StarRunTime);
                                if (startTime >= DateTimeOffset.Now.AddMonths(1 - DateTimeOffset.Now.Month).AddDays(1 - DateTimeOffset.Now.Day))
                                {
                                    scheduleInfo.StarRunTime = startTime;
                                }
                                else
                                {
                                    scheduleInfo.StarRunTime = DateTimeOffset.Now;
                                }
                            }

                            if (string.IsNullOrWhiteSpace(attr.EndRunTime))
                            {
                                scheduleInfo.EndRunTime = DateTime.Now.AddYears(100);
                            }
                            else
                            {
                                var endTime = DateTimeOffset.Parse(attr.EndRunTime);
                                if (endTime > DateTimeOffset.Now)
                                {
                                    scheduleInfo.EndRunTime = endTime;
                                }
                                else
                                {
                                    scheduleInfo.EndRunTime = DateTime.Now.AddYears(100);
                                }
                            }

                            scheduleInfo.JobType = item;
                            scheduleInfo.JobName = string.IsNullOrWhiteSpace(attr.JobName) ? item.Name : attr.JobName;
                            scheduleInfo.CromExpress = attr.CromExpress;

                            if (string.IsNullOrWhiteSpace(attr.CromExpress))
                            {
                                throw new JobException("运行时间设置错误 CromExpress Class:" + item.FullName);
                            }

                            String key = $"JOB:{scheduleInfo.JobGroup}.{scheduleInfo.JobName}";

                            IDictionary<String, object> map = new Dictionary<String, object>();

                            map.Add("JobGroup", scheduleInfo.JobGroup);
                            map.Add("JobName", scheduleInfo.JobName);
                            map.Add("StarRunTime", scheduleInfo.StarRunTime?.ToString("yyyy-MM-dd HH:mm:ss"));
                            map.Add("EndRunTime", scheduleInfo.EndRunTime?.ToString("yyyy-MM-dd HH:mm:ss"));
                            map.Add("CromExpress", scheduleInfo.CromExpress);
                            //foreach (var sitem in map)
                            //{
                            //    redis.HashSet(key, sitem.Key, sitem.Value.ToString());
                            //}

                            jobManager.AddScheduleJobAsync(scheduleInfo).Wait();
                        }
                    }
                    Task.Factory.StartNew(async () =>
                    {
                        await Task.Delay(2200);
                        await jobManager.Start();
                    });
                });
            }
            catch (Exception ex) { throw ex; }

            return app;
        }

    }
}
